package cn.xlsea.gen;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.CaseUtils;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xlsea
 * @since 2023-07-02
 */
@Slf4j
@Service
public class AizudaBootGenService {

    @Resource
    private FactoryProperties project;

    public void main(){
        log.info("开始执行");
        this.fileGenerator();
        log.info("执行完成");
    }

    private void fileGenerator() {
        String srcPath = project.getFactoryPath();
        File srcFile = new File(srcPath);
        File destRoot = new File(project.getServerRootPath());

        List<String> exclude = this.getExcludeFile();
        List<String> excludeSuffix = this.getExcludeFileSuffix();
        List<String> excludeDir = this.getExcludeDir();
        Map<String, String> replaceDirMap = this.getReplaceDirMap();
        Map<String, String> replaceFileMap = this.getReplaceFileMap();

        FileFilter filter = (file) -> {
            if (exclude.contains(file.getName())) {
                return false;
            }
            if (excludeSuffix.contains(StringUtils.substringAfterLast(file.getName(), "."))) {
                return false;
            }
            if (file.isDirectory() && excludeDir.contains(file.getName())){
                return false;
            }
            return true;
        };

        try {
            FileHelper.copyDirectory(srcFile, destRoot, filter, replaceDirMap, replaceFileMap);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try {
            this.fileContentFormat(destRoot);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void fileContentFormat (File destRoot) throws IOException {
        final String classNamePrefix = CaseUtils.toCamelCase(project.getProjectName(), true, '-', '_');
        final String varNamePrefix = CaseUtils.toCamelCase(project.getProjectName(), false, '-', '_');

        FileFormatter javaFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("java"));
        javaFormatter.replaceAll("com.aizuda", project.getPackagePrefix());
        javaFormatter.replaceAll("Aizuda", classNamePrefix);
        javaFormatter.replaceAll("aizuda", varNamePrefix);
        javaFormatter.replaceAll("爱组搭", project.getProjectTitle());
        javaFormatter.replaceAll("jobob", project.getAuthor());
        javaFormatter.replaceAll("hubin", project.getAuthor());
        javaFormatter.replaceAll("青苗", project.getAuthor());
        javaFormatter.format();

        FileFormatter gradleFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("gradle"));
        gradleFormatter.replaceAll("com.aizuda", project.getPackagePrefix());
        gradleFormatter.replaceAll("aizuda", varNamePrefix);
        gradleFormatter.replaceAll("爱组搭", project.getProjectTitle());
        gradleFormatter.replaceAll("青苗", project.getAuthor());
        gradleFormatter.replaceAll("jobob@qq.com", project.getMail());
        gradleFormatter.format();

        FileFormatter xmlFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("xml"));
        xmlFormatter.replaceAll("com.aizuda", project.getPackagePrefix());
        xmlFormatter.replaceAll("aizuda", varNamePrefix);
        xmlFormatter.replaceAll("爱组搭", project.getProjectTitle());
        xmlFormatter.format();

        FileFormatter ymlFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("yml"));
        ymlFormatter.replaceAll("aizuda", varNamePrefix);
        ymlFormatter.format();

        FileFormatter propertiesFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("properties"));
        propertiesFormatter.replaceAll("aizuda", project.getProjectName());
        propertiesFormatter.format();

        FileFormatter vmFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("vm"));
        vmFormatter.replaceAll("com.aizuda", project.getPackagePrefix());
        vmFormatter.replaceAll("aizuda", varNamePrefix);
        vmFormatter.format();

        FileFormatter sqlFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("sql"));
        sqlFormatter.replaceAll("aizuda", project.getProjectName());
        sqlFormatter.format();

        FileFormatter txtFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("txt"));
        txtFormatter.replaceAll("爱组搭", project.getProjectTitle());
        txtFormatter.format();

        FileFormatter importsFormatter = new FileFormatter(destRoot, FileFilterUtils.suffixFileFilter("imports"));
        importsFormatter.replaceAll("com.aizuda", project.getPackagePrefix());
        importsFormatter.replaceAll("aizuda", varNamePrefix);
        importsFormatter.replaceAll("Aizuda", classNamePrefix);
        importsFormatter.replaceAll("爱组搭", project.getProjectName());
        importsFormatter.format();
    }

    private List<String> getExcludeFile () {
        List<String> exclude = new ArrayList<>();
        exclude.add(".git");
        exclude.add(".gradle");
        exclude.add(".idea");
        exclude.add("aizuda-gen");
        exclude.add("aizuda-boot-web");
        exclude.add("aizuda-components-examples");
        exclude.add("README.md");
        exclude.add("target");
        exclude.add("logs");
        exclude.add("out");
        exclude.add(".jar");
        return exclude;
    }

    private List<String> getExcludeFileSuffix() {
        List<String> exclude = new ArrayList<>();
        exclude.add("jar");
        exclude.add("log");
        return exclude;
    }

    private List<String> getExcludeDir() {
        List<String> exclude = new ArrayList<>();
        exclude.add("logs");
        exclude.add("data");
        return exclude;
    }

    private Map<String, String> getReplaceDirMap () {
        Map<String, String> replaceDirMap = new LinkedHashMap<>();
        replaceDirMap.put("aizuda-", project.getProjectName() + "-");
        replaceDirMap.put("src/main/java/com/aizuda", "src/main/java/" + project.getPackagePrefix().replaceAll("\\.", "/"));
        return replaceDirMap;
    }

    private Map<String, String> getReplaceFileMap () {
        final String classNamePrefix = CaseUtils.toCamelCase(project.getProjectName(), true, new char[] { '-', '_' });
        Map<String, String> replaceFileMap = new LinkedHashMap<>();
        replaceFileMap.put("Aizuda", classNamePrefix);
        replaceFileMap.put("aizuda", project.getProjectName());
        return replaceFileMap;
    }

}
